﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Rappelz.GameServer
{
    public class RoamingManager
    {
        /// <summary>
        /// The instance!
        /// </summary>
        protected static RoamingManager m_instance;

        /// <summary>
        /// Returns the instance
        /// </summary>
        public static RoamingManager Instance
        {
            get
            {
                if (m_instance == null)
                    m_instance = new RoamingManager();
                return m_instance;
            }
        }

// VTable         :   , Type:  *
// Function       :   public static struct RoamingManager & RoamingManager::Instance()
// Function       :   public void RoamingManager::~RoamingManager()

        public bool RegisterRoamingInfo(int nID, Roamer.RoamingType eType, int nMoveSpeed, Roamer.HateType eHateType, uint nRespawnInterval, int nAttributeFlag, int nInitialX, int nInitialY)
        {
// .text:0054A99D itErase         = std::_Vector_iterator<unsigned char,std::allocator<unsigned char> > ptr -20h
// .text:0054A99D __scoped_lock   = XScopedLock ptr -18h
// .text:0054A99D lit             = std::_Vector_iterator<unsigned char,std::allocator<unsigned char> > ptr -14h
// .text:0054A99D nID             = dword ptr  8    8
// .text:0054A99D eType           = dword ptr  12   0Ch
// .text:0054A99D nMoveSpeed      = dword ptr  16   10h
// .text:0054A99D eHateType       = dword ptr  20   14h
// .text:0054A99D nRespawnInterval= dword ptr  24   18h
// .text:0054A99D nAttributeFlag  = dword ptr  28   1Ch
            List<byte> vLayers = new List<byte>();      // -56  -38h
            int nDungeonID;                     // 32   20h
            Roamer pRoamer = null;              // 36   24h

            if (this.m_bInitialized)
                return false;

            lock(this.m_vRoamer)
            {
                foreach (Roamer rm in this.m_vRoamer)
                {
                    if (rm.m_nID == nID)
                        return false;
                }

                int nChannedId = ChannelManager.GetChannelId(nInitialX,nInitialX);
                nDungeonID = 0;
                if (nChannedId != 0)
                {
                    ChannelManager.GetLayersOfChannel(nChannedId, ref vLayers);
                    nDungeonID = DungeonManager.Instance.GetDungeonID(nInitialX, nInitialX);
                    if (nDungeonID != 0)
                    {
//                         v20 = *(v9 - 48);
//                         *(v9 + 36) = 1;
//                         std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
//                             (v9 - 40),
//                             v20,
//                             (v9 - 56));
//                         std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
//                             (v9 - 32),
//                             *(v9 - 52),
//                             (v9 - 56));
//                         v21 = *(v9 - 28);
//                         v22 = *(v9 - 32);
//                         v23 = *(v9 - 36);
//                         *(v9 - 16) = v21;
//                         v24 = std::_Find<unsigned_char___enum__DungeonManager::_unnamed_tag_>(v21, v23, (v9 + 36));
//                         *(v9 - 16) = v24;
//                         *(v9 - 28) = v24;
//                         v25 = *(v9 - 48);
//                         *(v9 - 32) = v22;
//                         std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
//                             (v9 - 40),
//                             v25,
//                             (v9 - 56));
//                         if ( !std::_Vector_const_iterator<X2D::Point<float>_std::allocator<X2D::Point<float>>>::operator__(
//                                   (v9 - 32),
//                                   (v9 - 40)) )
//                         {
//                             v26.baseclass_0._Myptr = *(v9 - 16);
//                             v26.baseclass_0.baseclass_0.baseclass_0._Mycont = v22;
//                             std::vector<unsigned_char_std::allocator<unsigned_char>>::erase((v9 - 56), (v9 - 40), v26);
//                         }
                    }
                }
                else
                {
                    vLayers.Add(0);
                }

                foreach (byte layer in vLayers)
                {
                    pRoamer = new Roamer(nID,eType,nMoveSpeed,eHateType,nRespawnInterval,nAttributeFlag,nDungeonID != 0 && layer != 0 && layer != 1);
                    pRoamer.m_layer = layer;
                    this.m_vRoamer.Add(pRoamer);
                }
                if (nDungeonID != 0)
                {
//                    DungeonManager.Instance.RegisterDungeonRoamerInfo(nDungeonID, v34);
                }
            }
            return true;
        }

        public bool UnregisterRoamingInfo(int nID)
        {
            if (this.m_bInitialized)
            {
                lock(this.m_vRoamer)
                {
                    for(int i = this.m_vRoamer.Count-1; i >= 0; --i)
                    {
                        Roamer rm = this.m_vRoamer[i];
                        if (rm.m_nID == nID)
                        {
                            this.m_vRoamer.RemoveAt(i);
                            return true;
                        }
                    }
                }
            }
            return false;

        }
// Function       :   public const unsigned int GetRoamingInfoCount()

        public bool RegisterRoamingPointInfo(int nRoamingID, int nPosX, int nPosY)
        {
            bool result = false;
            lock(this.m_vRoamer)
            {
                foreach (Roamer rm in this.m_vRoamer)
                {
                    if (rm.m_nID == nRoamingID)
                    {
                        ArPosition pos = new ArPosition(nPosX,nPosY,0);
                        rm.AddRoamingPoint(pos);
                        result = true;
                    }
                }
            }
            return result;
        }

// Function       :   public const unsigned int RoamingManager::GetRoamingPointInfoCount(const int)

        public bool AddRoamingCreatureRespawnInfo(int nRoamingId, GameContent.RoamingCreatureRespawnInfo info)
        {
            bool result = false;
            lock(this.m_vRoamer)
            {
                foreach (Roamer rm in this.m_vRoamer)
                {
                    if (rm.m_nID == nRoamingId)
                    {
                        rm.AddCreatureRespawnInfo(info);
                        result = true;
                    }
                }
            }

            return result;
        }

        public bool Init()
        {
            if (this.m_bInitialized)
                return false;

            lock(this.m_vRoamer)
            {
                foreach(Roamer rm in this.m_vRoamer)
                {
                    if (rm.m_vRoamingPoint.Count > 0)
                    {
                        if (rm.priority != SchedulerObject.Priority.High)
                        {
                            if (!rm.m_bIsRaidDungeonRoamer)
                            {
                                rm.Init();
                            }
                        }
                    }
                }
                this.m_bInitialized = true;
            }
            return true;
        }
// Function       :   public const bool RoamingManager::DeInit()
// Function       :   public void RoamingManager::InitRoamer(const int, const int)
// Function       :   public void RoamingManager::DeInitRoamer(const int, const int)
// Function       :   public void RoamingManager(const struct RoamingManager &)
// Function       :   private void RoamingManager::RoamingManager()
// Data           :   this+0x4, Member, Type: class XCriticalSection, m_RoamerLock
// UserDefinedType:     XCriticalSection
// 
        public bool m_bInitialized;                         // 0x44
        public List<Roamer> m_vRoamer = new List<Roamer>(); // 0x48
    }
}
